

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/fluid.png">
  <link rel="icon" href="/img/fluid.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="czr">
  <meta name="keywords" content="">
  
    <meta name="description" content="SpringBoot整合Spring Security1.SpringSecurty简介​	1.Spring Security是Spring家族中的一个安全管理框架 ​	2.一般来说web应用的需要进行认证和授权 ​		认证：验证当前访问系统的是不是本系统的用户，并且要确认具体是哪个用户 ​		授权：经过认证后判断当前的用户是否有权限进行某个操作 ​	3.认证和授权也是SpringSecurity">
<meta property="og:type" content="article">
<meta property="og:title" content="SpringBoot整合Security">
<meta property="og:url" content="http://czrgitee.gitee.io/2022/08/25/SpringBoot%E6%95%B4%E5%90%88Security/index.html">
<meta property="og:site_name" content="安徒生">
<meta property="og:description" content="SpringBoot整合Spring Security1.SpringSecurty简介​	1.Spring Security是Spring家族中的一个安全管理框架 ​	2.一般来说web应用的需要进行认证和授权 ​		认证：验证当前访问系统的是不是本系统的用户，并且要确认具体是哪个用户 ​		授权：经过认证后判断当前的用户是否有权限进行某个操作 ​	3.认证和授权也是SpringSecurity">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2022-08-25T01:35:58.000Z">
<meta property="article:modified_time" content="2022-08-25T01:37:57.548Z">
<meta property="article:author" content="czr">
<meta name="twitter:card" content="summary_large_image">
  
  
  
  <title>SpringBoot整合Security - 安徒生</title>

  <link  rel="stylesheet" href="https://lib.baomitu.com/twitter-bootstrap/4.6.1/css/bootstrap.min.css" />



  <link  rel="stylesheet" href="https://lib.baomitu.com/github-markdown-css/4.0.0/github-markdown.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/hint.css/2.7.0/hint.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.css" />



<!-- 主题依赖的图标库，不要自行修改 -->
<!-- Do not modify the link that theme dependent icons -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_hj8rtnfg7um.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_lbnruvf0jn.css">


<link  rel="stylesheet" href="/css/main.css" />


  <link id="highlight-css" rel="stylesheet" href="/css/highlight.css" />
  
    <link id="highlight-css-dark" rel="stylesheet" href="/css/highlight-dark.css" />
  



  
<link rel="stylesheet" href="/css/macpanel.css">



  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    Fluid.ctx = Object.assign({}, Fluid.ctx)
    var CONFIG = {"hostname":"czrgitee.gitee.io","root":"/","version":"1.9.0","typing":{"enable":true,"typeSpeed":120,"cursorChar":"_","loop":false,"scope":[]},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"left","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"code_language":{"enable":true,"default":"TEXT"},"copy_btn":true,"image_caption":{"enable":true},"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"placement":"right","headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":1},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"follow_dnt":true,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname","ignore_local":false}},"search_path":"/local-search.xml"};

    if (CONFIG.web_analytics.follow_dnt) {
      var dntVal = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
      Fluid.ctx.dnt = dntVal && (dntVal.startsWith('1') || dntVal.startsWith('yes') || dntVal.startsWith('on'));
    }
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
  


  
<meta name="generator" content="Hexo 6.3.0"></head>


<body>
  

  <header>
    

<div class="header-inner" style="height: 70vh;">
  <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/">
      <strong>Andersen</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                <span>首页</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                <span>归档</span>
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              <i class="iconfont icon-search"></i>
            </a>
          </li>
          
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">
              <i class="iconfont icon-dark" id="color-toggle-icon"></i>
            </a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

  

<div id="banner" class="banner" parallax=true
     style="background: url('https://tuapi.eees.cc/api.php?category=fengjing&type=302') no-repeat center center; background-size: cover;">
  <div class="full-bg-img">
    <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
      <div class="banner-text text-center fade-in-up">
        <div class="h2">
          
            <span id="subtitle" data-typed-text="SpringBoot整合Security"></span>
          
        </div>

        
          
  <div class="mt-3">
    
    
      <span class="post-meta">
        <i class="iconfont icon-date-fill" aria-hidden="true"></i>
        <time datetime="2022-08-25 09:35" pubdate>
          2022年8月25日 上午
        </time>
      </span>
    
  </div>

  <div class="mt-1">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-chart"></i>
        
          37k 字
        
      </span>
    

    
      <span class="post-meta mr-2">
        <i class="iconfont icon-clock-fill"></i>
        
        
        
          306 分钟
        
      </span>
    

    
    
  </div>


        
      </div>

      
    </div>
  </div>
</div>

</div>

  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="side-col d-none d-lg-block col-lg-2">
      

    </div>

    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">SpringBoot整合Security</h1>
            
              <p class="note note-info">
                
                  
                    本文最后更新于：2022年8月25日 上午
                  
                
              </p>
            
            
              <div class="markdown-body">
                
                <h3 id="SpringBoot整合Spring-Security"><a href="#SpringBoot整合Spring-Security" class="headerlink" title="SpringBoot整合Spring Security"></a>SpringBoot整合Spring Security</h3><h4 id="1-SpringSecurty简介"><a href="#1-SpringSecurty简介" class="headerlink" title="1.SpringSecurty简介"></a>1.SpringSecurty简介</h4><p>​	1.Spring Security是Spring家族中的一个安全管理框架</p>
<p>​	2.一般来说web应用的需要进行认证和授权</p>
<p>​		认证：验证当前访问系统的是不是本系统的用户，并且要确认具体是哪个用户</p>
<p>​		授权：经过认证后判断当前的用户是否有权限进行某个操作</p>
<p>​	3.认证和授权也是SpringSecurity作为安全框架的核心功能。</p>
<h4 id="2-快速入门"><a href="#2-快速入门" class="headerlink" title="2.快速入门"></a>2.快速入门</h4><h4 id="2-1准备工作"><a href="#2-1准备工作" class="headerlink" title="2.1准备工作"></a>2.1准备工作</h4><h5 id="2-1准备一个springboot工程"><a href="#2-1准备一个springboot工程" class="headerlink" title="2.1准备一个springboot工程"></a>2.1准备一个springboot工程</h5><p>1.设置父工程的依赖</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs xml">    <span class="hljs-tag">&lt;<span class="hljs-name">parent</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-parent<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>2.5.5<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">relativePath</span>/&gt;</span> <span class="hljs-comment">&lt;!-- lookup parent from repository --&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">parent</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br><span class="hljs-comment">&lt;!--        启动器--&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-comment">&lt;!--        lombok插件--&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.projectlombok<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>lombok<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">optional</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">optional</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>2.新增controller测试</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RestController</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">WxUserController</span> &#123;<br>    <span class="hljs-meta">@RequestMapping(&quot;/hello&quot;)</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">Hello</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;ok&quot;</span>;<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<p>3.使用谷歌浏览器访问路径测试</p>
<figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs txt">http://localhost:8888/hello<br></code></pre></td></tr></table></figure>



<h5 id="2-2引入Spring-Security"><a href="#2-2引入Spring-Security" class="headerlink" title="2.2引入Spring Security"></a>2.2引入Spring Security</h5><p>1.引入依赖即可实现入门案例</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!--        集成spring security--&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-security<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>引入依赖之后我们尝试访问之前的接口会发现自动跳转到一个springsecurity的默认登录界面，默认用户名是user，密码会在控制台上输出。也就是必须要登录之后才能对接口进行访问。</p>
<h4 id="3-认证"><a href="#3-认证" class="headerlink" title="3.认证"></a>3.认证</h4><h5 id="3-1登录校验流程"><a href="#3-1登录校验流程" class="headerlink" title="3.1登录校验流程"></a>3.1登录校验流程</h5><h5 id="3-2SpringSecurity完整流程"><a href="#3-2SpringSecurity完整流程" class="headerlink" title="3.2SpringSecurity完整流程"></a>3.2SpringSecurity完整流程</h5><p>SpringSecurity的原理其实就是一个过滤器，内部包含了提供各种功能的过滤器，这里我们可以看看入门案例中的过滤器。</p>
<p>图中只是显示了核心过滤器，其他的非核心过滤器并没有在图中显示。</p>
<p><strong>UsernamePasswordAuthenticationFilter</strong>：负责处理我们在登录页面填写了用户名密码后的登录请求。入门案例找那个的认证工作主要有它负责。</p>
<p><strong>ExceptionTranslationFilter</strong>:处理过滤器链中抛出的任何AccessDeniedException和AuthenticationException.</p>
<p><strong>FilterSecurityInterceptor</strong>:负责权限校验的过滤器。</p>
<p>通过debug发现SpringSecurity的过滤器有这么多</p>
<h5 id="3-3-SpringSecurity认证流程图详解"><a href="#3-3-SpringSecurity认证流程图详解" class="headerlink" title="3.3 SpringSecurity认证流程图详解"></a>3.3 SpringSecurity认证流程图详解</h5><p>概念速查：</p>
<p>Authentication接口：它的实现类，表示当前访问系统的用户，封装了用户相关信息</p>
<p>AuthenticationManager接口：定义了认证Authentication的方法</p>
<p>UserDetailService接口：加载用户特定数据的核心接口。里面规定了根据一个用户名查询用户信息的方法。</p>
<p>UserDetails接口：提供核心用户信息。通过UserDetailsService 根据用户信息要封装成UserDetails对象返回。然后将这些信息封装到Authentication对象中。</p>
<p>具体登录流程</p>
<p>具体的检验流程</p>
<p>登录成功后就将用户id作为key 用户信息作为value存在redis中，然后在每次请求携带token时拿到用户id之后就去redis中取出用户信息，判断是否登录过了。</p>
<h5 id="3-4-解决问题"><a href="#3-4-解决问题" class="headerlink" title="3.4 解决问题"></a>3.4 解决问题</h5><h6 id="3-4-1思路分析"><a href="#3-4-1思路分析" class="headerlink" title="3.4.1思路分析"></a>3.4.1思路分析</h6><p>登录</p>
<p>​	1.自定义登录接口</p>
<p>​			调用ProviderManager的方法进行认证 如果认证成功生成jwt 把用户信息存入到redis中</p>
<p>​	2.自定义UserDetailsService</p>
<p>​			在这个实现类中去查询数据库</p>
<p>校验：</p>
<p>​	1.定义一个jwt认证过滤器</p>
<p>​			获取token</p>
<p>​			解析token，获取其中的userid</p>
<p>​			从redis中获取用户信息</p>
<p>​			存到SecurityContextHolder中</p>
<h5 id="3-5-准备工作"><a href="#3-5-准备工作" class="headerlink" title="3.5.准备工作"></a>3.5.准备工作</h5><p>​	1.整合redis、jwt、mybatis-plus、MySQL</p>
<p>​	2.测试可以使用mapper接口查询用户信息</p>
<p>​	3.用户表字段为 id、 user_name、password、 nick_name等</p>
<h5 id="3-6实现UserDetailsService"><a href="#3-6实现UserDetailsService" class="headerlink" title="3.6实现UserDetailsService"></a>3.6实现UserDetailsService</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.example.mybatisplusdemo.service.impl;<br><br><span class="hljs-keyword">import</span> com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;<br><span class="hljs-keyword">import</span> com.example.mybatisplusdemo.entity.LoginUser;<br><span class="hljs-keyword">import</span> com.example.mybatisplusdemo.entity.User;<br><br><span class="hljs-keyword">import</span> com.example.mybatisplusdemo.mapper.UserMapper;<br><br><span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;<br><span class="hljs-keyword">import</span> org.springframework.security.core.userdetails.UserDetails;<br><span class="hljs-keyword">import</span> org.springframework.security.core.userdetails.UserDetailsService;<br><span class="hljs-keyword">import</span> org.springframework.security.core.userdetails.UsernameNotFoundException;<br><span class="hljs-keyword">import</span> org.springframework.stereotype.Service;<br><br><span class="hljs-keyword">import</span> java.util.Objects;<br><br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> chenzj9</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Description</span> 重写security过滤器链中的UserDetailsService实现从数据库中查询用户信息</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@date</span> 2022年01月13日 16:39</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Service</span> <span class="hljs-comment">//注意一定要注入到spring容器中</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">UserDetailsServiceImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">UserDetailsService</span> &#123;<br>    <span class="hljs-meta">@Autowired</span><br>    <span class="hljs-keyword">private</span> UserMapper userMapper;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> UserDetails <span class="hljs-title function_">loadUserByUsername</span><span class="hljs-params">(String username)</span> <span class="hljs-keyword">throws</span> UsernameNotFoundException &#123;<br>    <span class="hljs-comment">//从数据库查询用户信息 这里我根据openID查询</span><br>        LambdaQueryWrapper&lt;User&gt; queryWrapper = <span class="hljs-keyword">new</span> <span class="hljs-title class_">LambdaQueryWrapper</span>&lt;&gt;();<br>        queryWrapper.eq(User::getUserName,username);<br>        <span class="hljs-type">User</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> userMapper.selectOne(queryWrapper);<br><span class="hljs-comment">//        如果查询到的用户信息为空，就抛出异常</span><br>        <span class="hljs-keyword">if</span>(Objects.isNull(user))&#123;<br>            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">&quot;用户openID错误或者是用户不存在&quot;</span>);<br>        &#125;<br>        <span class="hljs-comment">//TODO 查询用户的权限信息</span><br><br><span class="hljs-comment">//        把数据封装成UserDetails</span><br><br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">LoginUser</span>(user);<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<p>另外UserDetailsService返回的对象为UserDetails，所以要重新写一个对象封装</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.example.mybatisplusdemo.entity;<br><br><span class="hljs-keyword">import</span> lombok.AllArgsConstructor;<br><span class="hljs-keyword">import</span> lombok.Data;<br><span class="hljs-keyword">import</span> lombok.NoArgsConstructor;<br><span class="hljs-keyword">import</span> org.springframework.security.core.GrantedAuthority;<br><span class="hljs-keyword">import</span> org.springframework.security.core.userdetails.UserDetails;<br><br><span class="hljs-keyword">import</span> java.util.Collection;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> chenzj9</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Description</span> 重写一个用户实例对象用户security认证</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@date</span> 2022年01月13日 16:52</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Data</span><br><span class="hljs-meta">@NoArgsConstructor</span><br><span class="hljs-meta">@AllArgsConstructor</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">LoginUser</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">UserDetails</span> &#123;<br><span class="hljs-comment">//    定义一个自己的user对象</span><br>    <span class="hljs-keyword">private</span> User user;<br><span class="hljs-comment">//    返回权限</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> Collection&lt;? <span class="hljs-keyword">extends</span> <span class="hljs-title class_">GrantedAuthority</span>&gt; getAuthorities() &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">getPassword</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> user.getPassword();<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">getUsername</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> user.getUserName();<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isAccountNonExpired</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isAccountNonLocked</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>    &#125;<br><br><span class="hljs-comment">//    是否过期</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isCredentialsNonExpired</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isEnabled</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<p>接下来就可以重启项目访问之前的接口了，使用的是数据库中存在的用户表中的用户登录，然后会有一个密码存储的问题，接下来会讲到</p>
<h5 id="3-6密码加密存储"><a href="#3-6密码加密存储" class="headerlink" title="3.6密码加密存储"></a>3.6密码加密存储</h5><p>1.重写Security密码加密方式</p>
<p>加一个配置类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.example.mybatisplusdemo.config;<br><br><span class="hljs-keyword">import</span> org.springframework.context.annotation.Bean;<br><span class="hljs-keyword">import</span> org.springframework.context.annotation.Configuration;<br><span class="hljs-keyword">import</span> org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;<br><span class="hljs-keyword">import</span> org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;<br><span class="hljs-keyword">import</span> org.springframework.security.crypto.password.PasswordEncoder;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> chenzj9</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Description</span> security配置类</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@date</span> 2022年01月13日 17:44</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Configuration</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">SpringSecurityConfig</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">WebSecurityConfigurerAdapter</span> &#123;<br><span class="hljs-comment">//    BCryptPasswordEncoder创建默认的密码加密方式并注入容器</span><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> PasswordEncoder <span class="hljs-title function_">passwordEncoder</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">BCryptPasswordEncoder</span>();<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<p>2.注意这时候数据库存储的密码就是加密后的秘文了，不然登录会失败。</p>
<h5 id="3-7自定义登录接口"><a href="#3-7自定义登录接口" class="headerlink" title="3.7自定义登录接口"></a>3.7自定义登录接口</h5><p>1.自定义登录接口，然后让SpringSecurity对这个接口放行，就是不用登录认证也可以访问、</p>
<p>2.在接口中我们通过AuthenticationManager的authenticate方法进行用户认证，所以需要在securityConfig中把AuthenticationManager注入容器中。</p>
<p>3.认证成功的话返回一个jwt，放入到响应体中，并让用户下回请求时能通过jwt识别出具体的是哪个用户，我们需要把用户信息存入redis中，可以把用户id作为key</p>
<p>（1）定义一个接口类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RestController</span><br><span class="hljs-meta">@RequestMapping(&quot;/user&quot;)</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">LoginController</span> &#123;<br><br>    <span class="hljs-meta">@Autowired</span><br>    <span class="hljs-keyword">private</span> LoginService loginService;<br>    <span class="hljs-meta">@PostMapping(&quot;/login&quot;)</span><br>    <span class="hljs-keyword">public</span> Result <span class="hljs-title function_">login</span><span class="hljs-params">(<span class="hljs-meta">@RequestBody</span> User user)</span>&#123;<br>    <span class="hljs-comment">//登录</span><br><br>        <span class="hljs-keyword">return</span> loginService.login(user);<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<p>(2)定义一个登录服务类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title class_">LoginService</span> &#123;<br>    Result <span class="hljs-title function_">login</span><span class="hljs-params">(User user)</span>;<br>&#125;<br></code></pre></td></tr></table></figure>



<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Service</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">LoginServiceImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">LoginService</span> &#123;<br><br>    <span class="hljs-meta">@Autowired</span><br>    <span class="hljs-keyword">private</span> AuthenticationManager authenticationManager;<br><br>    <span class="hljs-meta">@Autowired</span><br>    <span class="hljs-keyword">private</span> RedisUtil redisUtil;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> Result <span class="hljs-title function_">login</span><span class="hljs-params">(User user)</span> &#123;<br>        <span class="hljs-comment">//AuthenticationManager authentication方法认证  需要去security配置类里配置</span><br>        <span class="hljs-comment">//将用户名和用户密码封装成authenticationToken对象</span><br>        <span class="hljs-type">UsernamePasswordAuthenticationToken</span> <span class="hljs-variable">authenticationToken</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">UsernamePasswordAuthenticationToken</span>(user.getUserName(), user.getPassword());<br>        <span class="hljs-type">Authentication</span> <span class="hljs-variable">authenticate</span> <span class="hljs-operator">=</span> authenticationManager.authenticate(authenticationToken);<br>        <span class="hljs-comment">//如果没认证通过返回提示</span><br>        <span class="hljs-keyword">if</span> (Objects.isNull(authenticate)) &#123;<br>            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">&quot;认证失败&quot;</span>);<br>        &#125;<br>        <span class="hljs-comment">//认证成功了使用userID返回一个jwt</span><br>        <span class="hljs-type">LoginUser</span> <span class="hljs-variable">loginUser</span> <span class="hljs-operator">=</span> (LoginUser) authenticate.getPrincipal();<br>        <span class="hljs-type">String</span> <span class="hljs-variable">userid</span> <span class="hljs-operator">=</span> loginUser.getUser().getId().toString();<br>        <span class="hljs-type">String</span> <span class="hljs-variable">jwt</span> <span class="hljs-operator">=</span> JwtUtils.getToken(userid);<br>        <span class="hljs-comment">//将完整的用户信息存入到redis中</span><br><br>        redisUtil.set(<span class="hljs-string">&quot;login:&quot;</span>+userid,loginUser);<br><br>        <span class="hljs-keyword">return</span> Result.success(<span class="hljs-string">&quot;登录成功&quot;</span>, <span class="hljs-string">&quot;token&quot;</span>, jwt);<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<p>(3)添加springSecurity配置</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Configuration</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">SpringSecurityConfig</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">WebSecurityConfigurerAdapter</span> &#123;<br>    <span class="hljs-comment">//    BCryptPasswordEncoder创建默认的密码加密方式并注入容器</span><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> PasswordEncoder <span class="hljs-title function_">passwordEncoder</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">BCryptPasswordEncoder</span>();<br>    &#125;<br><br>    <span class="hljs-comment">//    重写方法实现放行请求</span><br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">configure</span><span class="hljs-params">(HttpSecurity http)</span> <span class="hljs-keyword">throws</span> Exception &#123;<br>        http<br>            .csrf().disable() <span class="hljs-comment">//关闭csrf</span><br>            <span class="hljs-comment">//                关闭session会话机制</span><br>            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)<br>            .and()<br>            .authorizeRequests()<br>            <span class="hljs-comment">//对于登录接口 允许匿名访问</span><br>            .antMatchers(<span class="hljs-string">&quot;/user/login&quot;</span>).anonymous()<br>            <span class="hljs-comment">//除了上面的都要进行鉴权认证</span><br>            .anyRequest().authenticated();<br>        <span class="hljs-comment">//        super.configure(http);</span><br>    &#125;<br><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> AuthenticationManager <span class="hljs-title function_">authenticationManagerBean</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> Exception &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">super</span>.authenticationManagerBean();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h5 id="3-8认证过滤器"><a href="#3-8认证过滤器" class="headerlink" title="3.8认证过滤器"></a>3.8认证过滤器</h5><p>1.我们需要自定义一个过滤器，这个过滤器会去获取请求头中的token，对token进行解析取出其中的userID</p>
<p>2.使用userID去redis中获取对应的loginUser对象</p>
<p>3.然后封装成Authentication对象存入到SecurityContextHolder中</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.example.mybatisplusdemo.filter;<br><br><span class="hljs-keyword">import</span> com.example.mybatisplusdemo.entity.LoginUser;<br><span class="hljs-keyword">import</span> com.example.mybatisplusdemo.utils.JwtUtils;<br><span class="hljs-keyword">import</span> com.example.mybatisplusdemo.utils.RedisUtil;<br><span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;<br><span class="hljs-keyword">import</span> org.springframework.security.authentication.UsernamePasswordAuthenticationToken;<br><span class="hljs-keyword">import</span> org.springframework.security.core.context.SecurityContextHolder;<br><span class="hljs-keyword">import</span> org.springframework.stereotype.Component;<br><span class="hljs-keyword">import</span> org.springframework.util.StringUtils;<br><span class="hljs-keyword">import</span> org.springframework.web.filter.OncePerRequestFilter;<br><br><span class="hljs-keyword">import</span> javax.servlet.FilterChain;<br><span class="hljs-keyword">import</span> javax.servlet.ServletException;<br><span class="hljs-keyword">import</span> javax.servlet.http.HttpServletRequest;<br><span class="hljs-keyword">import</span> javax.servlet.http.HttpServletResponse;<br><span class="hljs-keyword">import</span> java.io.IOException;<br><span class="hljs-keyword">import</span> java.text.ParseException;<br><span class="hljs-keyword">import</span> java.util.Objects;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> chenzj9</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Description</span> 定义jwt认证过滤器</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@date</span> 2022年01月14日 14:49</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Component</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">JwtAuthenticationTokenFilter</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">OncePerRequestFilter</span> &#123;<br>    <span class="hljs-meta">@Autowired</span><br>    <span class="hljs-keyword">private</span> RedisUtil redisUtil;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">doFilterInternal</span><span class="hljs-params">(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)</span> <span class="hljs-keyword">throws</span> ServletException, IOException &#123;<br>        <span class="hljs-comment">//       获取token</span><br>        <span class="hljs-type">String</span> <span class="hljs-variable">token</span> <span class="hljs-operator">=</span> request.getHeader(<span class="hljs-string">&quot;token&quot;</span>);<br>        <span class="hljs-keyword">if</span>(!StringUtils.hasText(token))&#123;<br>            <span class="hljs-comment">//            为空时放行 因为后面还有别的过滤器</span><br>            filterChain.doFilter(request,response);<br>            <span class="hljs-keyword">return</span>; <span class="hljs-comment">//下面就不执行解析等操作了</span><br>        &#125;<br>        <span class="hljs-comment">//        解析token</span><br>        String userid;<br>        <span class="hljs-keyword">try</span> &#123;<br>            userid = (String) JwtUtils.parseToken(token);<br>        &#125; <span class="hljs-keyword">catch</span> (ParseException e) &#123;<br>            e.printStackTrace();<br>            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">&quot;token非法！&quot;</span>);<br>        &#125;<br>        <span class="hljs-comment">//        从redis中获取到用户信息</span><br>        <span class="hljs-type">Object</span> <span class="hljs-variable">o</span> <span class="hljs-operator">=</span> redisUtil.get(<span class="hljs-string">&quot;login:&quot;</span> + userid);<br>        <span class="hljs-type">LoginUser</span> <span class="hljs-variable">loginUser</span> <span class="hljs-operator">=</span> (LoginUser) o;<br>        <span class="hljs-keyword">if</span>(Objects.isNull(loginUser))&#123;<br>            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">&quot;用户未登录！&quot;</span>);<br>        &#125;<br>        <span class="hljs-comment">//        存入到SecurityContextHolder中，因为后面的过滤器都是从这里获取到认证的用户</span><br>        <span class="hljs-comment">//TODO 将用户权限信息存入到Authentication中</span><br>        <span class="hljs-type">UsernamePasswordAuthenticationToken</span> <span class="hljs-variable">authenticationToken</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">UsernamePasswordAuthenticationToken</span>(loginUser,<span class="hljs-literal">null</span>,<span class="hljs-literal">null</span>);<br>        SecurityContextHolder.getContext().setAuthentication(authenticationToken);<br>        <span class="hljs-comment">//        放行</span><br>        filterChain.doFilter(request,response);<br><br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>4.在security配置类中添加配置(其他同上) 因为jwt过滤器必须在UsernamePasswordAuthenticationFilter过滤器前</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Autowired</span><br><span class="hljs-keyword">private</span> JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;<br><span class="hljs-comment">//    重写方法实现放行请求</span><br><br><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">configure</span><span class="hljs-params">(HttpSecurity http)</span> <span class="hljs-keyword">throws</span> Exception &#123;<br>    http<br>        .csrf().disable() <span class="hljs-comment">//关闭csrf</span><br>        <span class="hljs-comment">//                关闭session会话机制</span><br>        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)<br>        .and()<br>        .authorizeRequests()<br>        <span class="hljs-comment">//对于登录接口 允许匿名访问</span><br>        .antMatchers(<span class="hljs-string">&quot;/user/login&quot;</span>).anonymous()<br>        <span class="hljs-comment">//除了上面的都要进行鉴权认证</span><br>        .anyRequest().authenticated();<br>    <span class="hljs-comment">//        super.configure(http);</span><br>    http<br>        <span class="hljs-comment">//                在UsernamePasswordAuthenticationFilter之前添加过滤器</span><br>        .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);<br>&#125;<br></code></pre></td></tr></table></figure>

<h5 id="3-9退出登录"><a href="#3-9退出登录" class="headerlink" title="3.9退出登录"></a>3.9退出登录</h5><p>​	我们只需要在loginController中定义一个退出登录接口，然后获取SecurityContextHolder中的认证信息，删除redis中的token数据。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@GetMapping(&quot;/logout&quot;)</span><br><span class="hljs-keyword">public</span> Result <span class="hljs-title function_">logout</span><span class="hljs-params">()</span>&#123;<br>    <span class="hljs-keyword">return</span> loginService.logout();<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//在loginService中定义logout方法</span><br>Result <span class="hljs-title function_">logout</span><span class="hljs-params">()</span>;<br><span class="hljs-comment">//在loginServiceImpl中实现逻辑</span><br><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">public</span> Result <span class="hljs-title function_">logout</span><span class="hljs-params">()</span> &#123;<br>    <span class="hljs-comment">//获取SecurityContextHolder中的用户id</span><br>    <span class="hljs-type">UsernamePasswordAuthenticationToken</span> <span class="hljs-variable">authenticationToken</span> <span class="hljs-operator">=</span> (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();<br>    <span class="hljs-type">LoginUser</span> <span class="hljs-variable">loginUser</span> <span class="hljs-operator">=</span> (LoginUser) authenticationToken.getPrincipal();<br>    <span class="hljs-comment">//删除redis中的数据</span><br>    <span class="hljs-type">Long</span> <span class="hljs-variable">userid</span> <span class="hljs-operator">=</span> loginUser.getUser().getId();<br>    redisUtil.delete(<span class="hljs-string">&quot;login:&quot;</span>+userid.toString());<br>    <span class="hljs-keyword">return</span> Result.success(<span class="hljs-string">&quot;退出登录成功！&quot;</span>);<br>&#125;<br></code></pre></td></tr></table></figure>

<p>然后就先登录在访问hello接口测试，然后在访问logout接口，最后访问hello接口发现已经未登录（注意：除了登录接口其他接口访问都要携带token）</p>
<h4 id="4-授权"><a href="#4-授权" class="headerlink" title="4.授权"></a>4.授权</h4><h5 id="4-0权限系统的作用"><a href="#4-0权限系统的作用" class="headerlink" title="4.0权限系统的作用"></a>4.0权限系统的作用</h5><p> 例如一个学校图书管理系统，如果是普通学生就能看到借书和还书相关功能，不可能让他看到并且去使用添加书籍信息，删除数据信息相关功能。但是如果是一个图书管理员的账号登录了，应该就能看到并使用添加书籍信息，删除书籍信息等相关功能。</p>
<p>​	总结起来就是不同的用户可以使用不同的功能，这就是权限系统要去实现的效果。</p>
<p>​	我们不能只依赖前端去判断用户的权限来选择显示那些菜单那些按钮。因为如果只这样，如果有人知道了对应功能的接口地址就可以不通过前端，直接去发送请求来实现相关功能操作。</p>
<p>​	所以我们还要在后台进行用户权限的判断，判断当前用户是否有相应的权限，必须基于所需权限才能进行相应的操作。</p>
<h5 id="4-1授权基本流程"><a href="#4-1授权基本流程" class="headerlink" title="4.1授权基本流程"></a>4.1授权基本流程</h5><p>​	在springSecurity中，会使用默认的filterSecurityInterceptor来进行权限校验。在filterSecurityInterceptor中会从SecurityContextHolder获取其中的Authentication。然后获取其中的权限信息。当前用户是否拥有访问当前资源所需的权限。</p>
<p>​	所以我们在项目中只需要把当前登录用户的权限信息也存入到Authentication.</p>
<p>​	然后设置我们的资源所需的权限就行。</p>
<h5 id="4-2授权实现"><a href="#4-2授权实现" class="headerlink" title="4.2授权实现"></a>4.2授权实现</h5><h6 id="4-2-1限制访问资源所需权限"><a href="#4-2-1限制访问资源所需权限" class="headerlink" title="4.2.1限制访问资源所需权限"></a>4.2.1限制访问资源所需权限</h6><p>​	在SpringSecurity为我们提供了基于注解的权限控制方案，这也是我们项目中主要采用的方式。我们可以使用注解去指定访问对应职院的所需权限。</p>
<p>​	但是要使用它我们需要开启相关配置。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//在配置类SpringSecurityConfig类上加上这个注解</span><br><span class="hljs-meta">@EnableGlobalMethodSecurity(prePostEnabled = true)</span> <span class="hljs-comment">//开启是用prePostEnabled的注解</span><br></code></pre></td></tr></table></figure>



<p>​	然后就可以使用对应的注解。@PreAuthorize</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RequestMapping(&quot;/hello&quot;)</span><br><span class="hljs-meta">@PreAuthorize(&quot;hasAuthority(&#x27;test&#x27;)&quot;)</span><br><span class="hljs-keyword">public</span> String <span class="hljs-title function_">Hello</span><span class="hljs-params">()</span>&#123;<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;ok&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h6 id="4-2-2封装权限信息"><a href="#4-2-2封装权限信息" class="headerlink" title="4.2.2封装权限信息"></a>4.2.2封装权限信息</h6><p>​	我们前面在写UserDetailsServiceimpl的时候说过，在查询出用户后还需要获取对应的权限信息，封装到UserDetails中返回。</p>
<p>我们之前定义了UserDetails的实现类LoginUser。想要让其能封装权限信息就要对其进行修改。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.example.mybatisplusdemo.entity;<br><br><span class="hljs-keyword">import</span> com.alibaba.fastjson.annotation.JSONField;<br><span class="hljs-keyword">import</span> com.fasterxml.jackson.annotation.JsonIgnoreProperties;<br><span class="hljs-keyword">import</span> lombok.AllArgsConstructor;<br><span class="hljs-keyword">import</span> lombok.Data;<br><span class="hljs-keyword">import</span> lombok.NoArgsConstructor;<br><span class="hljs-keyword">import</span> lombok.extern.java.Log;<br><span class="hljs-keyword">import</span> org.springframework.security.core.GrantedAuthority;<br><span class="hljs-keyword">import</span> org.springframework.security.core.authority.SimpleGrantedAuthority;<br><span class="hljs-keyword">import</span> org.springframework.security.core.userdetails.UserDetails;<br><br><br><span class="hljs-keyword">import</span> java.io.Serializable;<br><span class="hljs-keyword">import</span> java.util.ArrayList;<br><span class="hljs-keyword">import</span> java.util.Collection;<br><span class="hljs-keyword">import</span> java.util.List;<br><span class="hljs-keyword">import</span> java.util.stream.Collectors;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> chenzj9</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Description</span> 重写一个用户实例对象用户security认证</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@date</span> 2022年01月13日 16:52</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Data</span><br><span class="hljs-meta">@NoArgsConstructor</span><br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">LoginUser</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">UserDetails</span> &#123;<br><span class="hljs-comment">//    定义一个自己的user对象</span><br><br>    <span class="hljs-keyword">private</span> User user;<br>    <span class="hljs-comment">//权限信息</span><br>    <span class="hljs-keyword">private</span> List&lt;String&gt; permission;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">LoginUser</span><span class="hljs-params">(User user, List&lt;String&gt; permission)</span> &#123;<br>        <span class="hljs-built_in">this</span>.user = user;<br>        <span class="hljs-built_in">this</span>.permission = permission;<br>    &#125;<br>    <span class="hljs-comment">//权限信息列表 不需要序列化</span><br>    <span class="hljs-meta">@JSONField(serialize = false)</span><br>    <span class="hljs-keyword">private</span> List&lt;SimpleGrantedAuthority&gt; authorityList;<br>    <span class="hljs-comment">//    返回权限</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> Collection&lt;? <span class="hljs-keyword">extends</span> <span class="hljs-title class_">GrantedAuthority</span>&gt; getAuthorities() &#123;<br>        <span class="hljs-comment">//把permission中的string类型的权限信息封装成SimpleGrantedAuthority对象</span><br>        <span class="hljs-comment">//判断权限信息是否已存在，存在直接返回</span><br>        <span class="hljs-keyword">if</span>(authorityList!=<span class="hljs-literal">null</span>)&#123;<br>            <span class="hljs-keyword">return</span> authorityList;<br>        &#125;<br><span class="hljs-comment">//         authorityList = new ArrayList&lt;&gt;();</span><br><span class="hljs-comment">//        for (String role : permission) &#123;</span><br><span class="hljs-comment">//            SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(role);</span><br><span class="hljs-comment">//            authorityList.add(simpleGrantedAuthority);</span><br><span class="hljs-comment">//        &#125;</span><br>        <span class="hljs-comment">//或者使用流对象处理</span><br>         authorityList = permission.stream().map(SimpleGrantedAuthority::<span class="hljs-keyword">new</span>).collect(Collectors.toList());<br>        <span class="hljs-keyword">return</span> authorityList;<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">getPassword</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> user.getPassword();<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">getUsername</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> user.getUserName();<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isAccountNonExpired</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isAccountNonLocked</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>    &#125;<br><br><span class="hljs-comment">//    是否过期</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isCredentialsNonExpired</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isEnabled</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<p>接下来就是修改jwt过滤器了</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.example.mybatisplusdemo.filter;<br><br><span class="hljs-keyword">import</span> com.example.mybatisplusdemo.entity.LoginUser;<br><span class="hljs-keyword">import</span> com.example.mybatisplusdemo.utils.JwtUtils;<br><span class="hljs-keyword">import</span> com.example.mybatisplusdemo.utils.RedisCache;<br><span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;<br><span class="hljs-keyword">import</span> org.springframework.security.authentication.UsernamePasswordAuthenticationToken;<br><span class="hljs-keyword">import</span> org.springframework.security.core.context.SecurityContextHolder;<br><span class="hljs-keyword">import</span> org.springframework.stereotype.Component;<br><span class="hljs-keyword">import</span> org.springframework.util.StringUtils;<br><span class="hljs-keyword">import</span> org.springframework.web.filter.OncePerRequestFilter;<br><br><span class="hljs-keyword">import</span> javax.servlet.FilterChain;<br><span class="hljs-keyword">import</span> javax.servlet.ServletException;<br><span class="hljs-keyword">import</span> javax.servlet.http.HttpServletRequest;<br><span class="hljs-keyword">import</span> javax.servlet.http.HttpServletResponse;<br><span class="hljs-keyword">import</span> java.io.IOException;<br><span class="hljs-keyword">import</span> java.text.ParseException;<br><span class="hljs-keyword">import</span> java.util.Objects;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> chenzj9</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Description</span> 定义jwt认证过滤器</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@date</span> 2022年01月14日 14:49</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Component</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">JwtAuthenticationTokenFilter</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">OncePerRequestFilter</span> &#123;<br>    <span class="hljs-meta">@Autowired</span><br>    <span class="hljs-keyword">private</span> RedisCache redisCache;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">doFilterInternal</span><span class="hljs-params">(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)</span> <span class="hljs-keyword">throws</span> ServletException, IOException &#123;<br><span class="hljs-comment">//       获取token</span><br>        <span class="hljs-type">String</span> <span class="hljs-variable">token</span> <span class="hljs-operator">=</span> request.getHeader(<span class="hljs-string">&quot;token&quot;</span>);<br>        <span class="hljs-keyword">if</span> (!StringUtils.hasText(token)) &#123;<br><span class="hljs-comment">//            为空时放行 因为后面还有别的过滤器</span><br>            filterChain.doFilter(request, response);<br>            <span class="hljs-keyword">return</span>; <span class="hljs-comment">//下面就不执行解析等操作了</span><br>        &#125;<br><span class="hljs-comment">//        解析token</span><br>        String userid;<br>        <span class="hljs-keyword">try</span> &#123;<br>            userid = (String) JwtUtils.parseToken(token);<br>        &#125; <span class="hljs-keyword">catch</span> (ParseException e) &#123;<br>            e.printStackTrace();<br>            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">&quot;token非法！&quot;</span>);<br>        &#125;<br><span class="hljs-comment">//        从redis中获取到用户信息</span><br><span class="hljs-comment">//        Object o = redisUtil.get(&quot;login:&quot; + userid);</span><br>        <span class="hljs-type">LoginUser</span> <span class="hljs-variable">loginUser</span> <span class="hljs-operator">=</span> redisCache.getCacheObject(<span class="hljs-string">&quot;login:&quot;</span> + userid);<br><span class="hljs-comment">//        LoginUser loginUser = (LoginUser) o;</span><br>        <span class="hljs-keyword">if</span> (Objects.isNull(loginUser)) &#123;<br>            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">&quot;用户未登录！&quot;</span>);<br>        &#125;<br><span class="hljs-comment">//        存入到SecurityContextHolder中，因为后面的过滤器都是从这里获取到认证的用户</span><br>        <span class="hljs-comment">//TODO 将用户权限信息存入到Authentication中</span><br>        <span class="hljs-type">UsernamePasswordAuthenticationToken</span> <span class="hljs-variable">authenticationToken</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">UsernamePasswordAuthenticationToken</span>(loginUser, <span class="hljs-literal">null</span>, loginUser.getAuthorities());<br>        SecurityContextHolder.getContext().setAuthentication(authenticationToken);<br><span class="hljs-comment">//        放行</span><br>        filterChain.doFilter(request, response);<br><br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>然后进行测试</p>
<h6 id="4-2-3从数据库中查询权限信息"><a href="#4-2-3从数据库中查询权限信息" class="headerlink" title="4.2.3从数据库中查询权限信息"></a>4.2.3从数据库中查询权限信息</h6><h6 id="4-2-3-1-RBAC模型"><a href="#4-2-3-1-RBAC模型" class="headerlink" title="4.2.3.1 RBAC模型"></a>4.2.3.1 RBAC模型</h6><p>​	RBAC权限模型（Role-Based Access Control）即基于角色的权限控制。这是目前最常被开发者使用也是相对易用、通用权限模型。</p>
<p>图解</p>
<h6 id="4-2-3-2准备工作"><a href="#4-2-3-2准备工作" class="headerlink" title="4.2.3.2准备工作"></a>4.2.3.2准备工作</h6><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">drop</span> database mybatisdemo;<br><span class="hljs-keyword">create</span> database <span class="hljs-comment">/*! if not exists*/</span> `mybatisdemo` <span class="hljs-comment">/*! default character set utf8mb4*/</span>;<br><br>use `mybatisdemo`;<br><span class="hljs-comment">-- 菜单表</span><br><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> IF <span class="hljs-keyword">EXISTS</span> `sys_menu`;<br><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> `sys_menu`(<br>	`id` <span class="hljs-type">bigint</span>(<span class="hljs-number">20</span>) <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> auto_increment,<br>    `menu_name` <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>) <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> <span class="hljs-keyword">default</span> <span class="hljs-string">&#x27;null&#x27;</span> comment <span class="hljs-string">&#x27;菜单名&#x27;</span>,<br>    `path` <span class="hljs-type">varchar</span>(<span class="hljs-number">200</span>) <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;路由地址&#x27;</span>,<br>    `component` <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span> comment<span class="hljs-string">&#x27;组件名称&#x27;</span>,<br>    `visible` <span class="hljs-type">char</span>(<span class="hljs-number">1</span>) <span class="hljs-keyword">default</span> <span class="hljs-string">&#x27;0&#x27;</span> comment <span class="hljs-string">&#x27;菜单状态（0 显示，1 隐藏）&#x27;</span>,<br>    `status` <span class="hljs-type">char</span>(<span class="hljs-number">1</span>) <span class="hljs-keyword">default</span> <span class="hljs-string">&#x27;0&#x27;</span> comment <span class="hljs-string">&#x27;菜单状态（0 正常 1 停用）&#x27;</span>,<br>    `perms` <span class="hljs-type">varchar</span>(<span class="hljs-number">100</span>) <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;权限标识&#x27;</span>,<br>    `icon` <span class="hljs-type">varchar</span>(<span class="hljs-number">100</span>) <span class="hljs-keyword">default</span> <span class="hljs-string">&#x27;#&#x27;</span> comment<span class="hljs-string">&#x27;菜单图标&#x27;</span>,<br>    `create_by` <span class="hljs-type">bigint</span>(<span class="hljs-number">20</span>) <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span>,<br>    `create_time` datetime <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span>,<br>    `update_by` <span class="hljs-type">bigint</span>(<span class="hljs-number">20</span>) <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span>,<br>    `update_time` datetime <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span>,<br>    `del_flag` <span class="hljs-type">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">default</span> <span class="hljs-string">&#x27;0&#x27;</span> comment <span class="hljs-string">&#x27;是否删除（0 未删除 1 已删除）&#x27;</span>,<br>    `remark` <span class="hljs-type">varchar</span> (<span class="hljs-number">500</span>) <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;备注&#x27;</span>,<br>    <span class="hljs-keyword">primary</span> key(`id`)<br>    )engine<span class="hljs-operator">=</span>InnoDB AUTO_INCREMENT<span class="hljs-operator">=</span><span class="hljs-number">2</span> <span class="hljs-keyword">default</span> CHARSET <span class="hljs-operator">=</span> utf8mb4 comment <span class="hljs-operator">=</span> <span class="hljs-string">&#x27;菜单表&#x27;</span>;<br><span class="hljs-comment">-- 规则表</span><br><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> IF <span class="hljs-keyword">EXISTS</span> `sys_role`;<br><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> `sys_role`(<br>	`id` <span class="hljs-type">bigint</span>(<span class="hljs-number">20</span>) <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> auto_increment,<br>    `name` <span class="hljs-type">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span>,<br>    `role_key` <span class="hljs-type">varchar</span>(<span class="hljs-number">100</span>) <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span> comment<span class="hljs-string">&#x27;角色权限字符串&#x27;</span>,<br>    `status` <span class="hljs-type">char</span>(<span class="hljs-number">1</span>) <span class="hljs-keyword">default</span> <span class="hljs-string">&#x27;0&#x27;</span> comment <span class="hljs-string">&#x27;角色状态（0 正常 1 停用）&#x27;</span>,<br>    `del_flag` <span class="hljs-type">int</span>(<span class="hljs-number">1</span>) <span class="hljs-keyword">default</span> <span class="hljs-number">0</span> comment <span class="hljs-string">&#x27;删除标识&#x27;</span>,<br>    `create_by` <span class="hljs-type">bigint</span>(<span class="hljs-number">20</span>) <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span>,<br>    `create_time` datetime <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span>,<br>    `update_by` <span class="hljs-type">bigint</span>(<span class="hljs-number">20</span>) <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span>,<br>    `update_time` datetime <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span>,<br>    `remark` <span class="hljs-type">varchar</span>(<span class="hljs-number">500</span>) <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span> comment<span class="hljs-string">&#x27;备注&#x27;</span>,<br>	<span class="hljs-keyword">primary</span> key(`id`)<br>)engine<span class="hljs-operator">=</span>InnoDB AUTO_INCREMENT<span class="hljs-operator">=</span><span class="hljs-number">2</span> <span class="hljs-keyword">default</span> CHARSET <span class="hljs-operator">=</span> utf8mb4 comment <span class="hljs-operator">=</span> <span class="hljs-string">&#x27;角色表&#x27;</span>;<br><span class="hljs-comment">-- 角色菜单表</span><br><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> IF <span class="hljs-keyword">EXISTS</span> `sys_role_menu`;<br><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> `sys_role_menu`(<br>	`role_id` <span class="hljs-type">bigint</span>(<span class="hljs-number">200</span>) <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> auto_increment comment<span class="hljs-string">&#x27;角色id&#x27;</span>,<br>	`menu_id` <span class="hljs-type">bigint</span>(<span class="hljs-number">200</span>) <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> <span class="hljs-keyword">default</span> <span class="hljs-number">0</span> comment<span class="hljs-string">&#x27;菜单id&#x27;</span>,<br>	<span class="hljs-keyword">primary</span> key(`role_id`,`menu_id`)<br>)engine<span class="hljs-operator">=</span>InnoDB AUTO_INCREMENT<span class="hljs-operator">=</span><span class="hljs-number">2</span> <span class="hljs-keyword">default</span> CHARSET <span class="hljs-operator">=</span> utf8mb4 comment <span class="hljs-operator">=</span> <span class="hljs-string">&#x27;角色菜单映射表&#x27;</span>;<br><span class="hljs-comment">-- 用户表</span><br><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> IF <span class="hljs-keyword">EXISTS</span> `sys_user`;<br><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> `sys_user`(<br>	`id` <span class="hljs-type">bigint</span>(<span class="hljs-number">20</span>) <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> auto_increment comment<span class="hljs-string">&#x27;主键&#x27;</span>,<br>    `user_name` <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>) <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> <span class="hljs-keyword">default</span> <span class="hljs-string">&#x27;null&#x27;</span> comment<span class="hljs-string">&#x27;用户名&#x27;</span>,<br>    `nick_name` <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>) <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> <span class="hljs-keyword">default</span> <span class="hljs-string">&#x27;null&#x27;</span> comment<span class="hljs-string">&#x27;密码&#x27;</span>,<br>    `password` <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>) <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> <span class="hljs-keyword">default</span> <span class="hljs-string">&#x27;null&#x27;</span> comment<span class="hljs-string">&#x27;用户密码&#x27;</span>,<br>    `status` <span class="hljs-type">char</span>(<span class="hljs-number">1</span>) <span class="hljs-keyword">default</span> <span class="hljs-string">&#x27;0&#x27;</span> comment<span class="hljs-string">&#x27;账号状态（0 正常 1 ,停用）&#x27;</span>,<br>	`email` <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>) <span class="hljs-keyword">default</span> <span class="hljs-string">&#x27;null&#x27;</span> comment<span class="hljs-string">&#x27;邮箱&#x27;</span>,<br>    `phonenumber` <span class="hljs-type">varchar</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">default</span> <span class="hljs-string">&#x27;null&#x27;</span> comment<span class="hljs-string">&#x27;手机号&#x27;</span>,<br>    `sex` <span class="hljs-type">char</span>(<span class="hljs-number">1</span>) <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span> comment<span class="hljs-string">&#x27;用户性别（0 男 1 女 2 未知）&#x27;</span>,<br>    `avatar` <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">default</span> <span class="hljs-string">&#x27;null&#x27;</span> comment<span class="hljs-string">&#x27;头像&#x27;</span>,<br>    `user_type` <span class="hljs-type">char</span>(<span class="hljs-number">1</span>) <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> <span class="hljs-keyword">default</span> <span class="hljs-string">&#x27;1&#x27;</span> comment<span class="hljs-string">&#x27;用户类型（0 管理员 1 普通用户）&#x27;</span>,<br>    `del_flag` <span class="hljs-type">int</span>(<span class="hljs-number">1</span>) <span class="hljs-keyword">default</span> <span class="hljs-number">0</span> comment <span class="hljs-string">&#x27;删除标识&#x27;</span>,<br>    `create_by` <span class="hljs-type">bigint</span>(<span class="hljs-number">20</span>) <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span>,<br>    `create_time` datetime <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span>,<br>    `update_by` <span class="hljs-type">bigint</span>(<span class="hljs-number">20</span>) <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span>,<br>    `update_time` datetime <span class="hljs-keyword">default</span> <span class="hljs-keyword">null</span>,<br>    <span class="hljs-keyword">primary</span> key(`id`)<br>)engine<span class="hljs-operator">=</span>InnoDB AUTO_INCREMENT<span class="hljs-operator">=</span><span class="hljs-number">2</span> <span class="hljs-keyword">default</span> CHARSET <span class="hljs-operator">=</span> utf8mb4 comment <span class="hljs-operator">=</span> <span class="hljs-string">&#x27;用户表&#x27;</span>;<br><br><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> IF <span class="hljs-keyword">EXISTS</span> `sys_user_role`;<br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> `sys_user_role`(<br>	`user_id` <span class="hljs-type">bigint</span>(<span class="hljs-number">200</span>) <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> auto_increment comment<span class="hljs-string">&#x27;用户id&#x27;</span>,<br>    `role_id` <span class="hljs-type">bigint</span>(<span class="hljs-number">200</span>) <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> <span class="hljs-keyword">default</span> <span class="hljs-string">&#x27;0&#x27;</span> comment<span class="hljs-string">&#x27;角色id&#x27;</span>,<br>    <span class="hljs-keyword">primary</span> key(`user_id`,`role_id`)<br>)engine<span class="hljs-operator">=</span>InnoDB AUTO_INCREMENT<span class="hljs-operator">=</span><span class="hljs-number">2</span> <span class="hljs-keyword">default</span> CHARSET <span class="hljs-operator">=</span> utf8mb4 comment <span class="hljs-operator">=</span> <span class="hljs-string">&#x27;用户角色映射表&#x27;</span>;<br><br><br></code></pre></td></tr></table></figure>

<p>权限查询语句</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 根据用户id 查询perms 对应的role 和menu 都必须是正常状态的alter</span><br><span class="hljs-keyword">SELECT</span> <br>    <span class="hljs-keyword">distinct</span> m.`perms`<br><span class="hljs-keyword">FROM</span><br>    sys_user_role <span class="hljs-keyword">as</span> ur<br>    <span class="hljs-keyword">left</span> <span class="hljs-keyword">join</span> `sys_role` r <span class="hljs-keyword">on</span> ur.`role_id` <span class="hljs-operator">=</span> r.`id`<br>    <span class="hljs-keyword">left</span> <span class="hljs-keyword">join</span> `sys_role_menu` rm <span class="hljs-keyword">on</span> ur.`role_id` <span class="hljs-operator">=</span> rm.`role_id`<br>    <span class="hljs-keyword">left</span> <span class="hljs-keyword">join</span> `sys_menu` m <span class="hljs-keyword">on</span> m.`id` <span class="hljs-operator">=</span> rm.`menu_id`<br><span class="hljs-keyword">WHERE</span><br>    user_id <span class="hljs-operator">=</span> <span class="hljs-number">2</span><br>	<span class="hljs-keyword">and</span> r.`status` <span class="hljs-operator">=</span> <span class="hljs-number">0</span><br>    <span class="hljs-keyword">and</span> m.`status` <span class="hljs-operator">=</span> <span class="hljs-number">0</span><br></code></pre></td></tr></table></figure>

<p>创建实体类User、Menu</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.example.mybatisplusdemo.entity;<br><br><span class="hljs-keyword">import</span> com.alibaba.fastjson.annotation.JSONField;<br><span class="hljs-keyword">import</span> com.baomidou.mybatisplus.annotation.TableId;<br><span class="hljs-keyword">import</span> com.baomidou.mybatisplus.annotation.TableName;<br><span class="hljs-keyword">import</span> com.fasterxml.jackson.annotation.JsonInclude;<br><span class="hljs-keyword">import</span> lombok.AllArgsConstructor;<br><span class="hljs-keyword">import</span> lombok.Data;<br><span class="hljs-keyword">import</span> lombok.NoArgsConstructor;<br><br><span class="hljs-keyword">import</span> java.io.Serializable;<br><span class="hljs-keyword">import</span> java.util.Date;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> chenzj9</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Description</span></span><br><span class="hljs-comment"> * <span class="hljs-doctag">@date</span> 2022年01月13日 17:07</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Data</span><br><span class="hljs-meta">@AllArgsConstructor</span><br><span class="hljs-meta">@NoArgsConstructor</span><br><span class="hljs-meta">@TableName(value = &quot;sys_user&quot;)</span><br><span class="hljs-meta">@JsonInclude(JsonInclude.Include.NON_NULL)</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">User</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">Serializable</span> &#123;<br>    <span class="hljs-meta">@TableId</span><br>    <span class="hljs-keyword">private</span> Long id;<br>    <span class="hljs-keyword">private</span> String userName;<br>    <span class="hljs-keyword">private</span> String nickName;<br>    <span class="hljs-keyword">private</span> String password;<br>    <span class="hljs-keyword">private</span> String status;<br>    <span class="hljs-keyword">private</span> String email;<br>    <span class="hljs-keyword">private</span> String phonenumber;<br>    <span class="hljs-keyword">private</span> String sex;<br>    <span class="hljs-keyword">private</span> String avatar;<br>    <span class="hljs-keyword">private</span> String user_type;<br>    <span class="hljs-keyword">private</span> Integer delFlag;<br>    <span class="hljs-keyword">private</span> Long  createBy;<br>    <span class="hljs-keyword">private</span> Date createTime;<br>    <span class="hljs-keyword">private</span> Long updateBy;<br>    <span class="hljs-keyword">private</span> Date updateTime;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.example.mybatisplusdemo.entity;<br><br><span class="hljs-keyword">import</span> com.baomidou.mybatisplus.annotation.TableId;<br><span class="hljs-keyword">import</span> com.fasterxml.jackson.annotation.JsonInclude;<br><span class="hljs-keyword">import</span> lombok.AllArgsConstructor;<br><span class="hljs-keyword">import</span> lombok.Data;<br><span class="hljs-keyword">import</span> lombok.NoArgsConstructor;<br><span class="hljs-keyword">import</span> lombok.experimental.Accessors;<br><br><span class="hljs-keyword">import</span> java.io.Serializable;<br><span class="hljs-keyword">import</span> java.util.Date;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> chenzj9</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Description</span></span><br><span class="hljs-comment"> * <span class="hljs-doctag">@date</span> 2022年01月20日 22:23</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Data</span><br><span class="hljs-meta">@AllArgsConstructor</span><br><span class="hljs-meta">@NoArgsConstructor</span><br><span class="hljs-meta">@Accessors(chain = true)</span><span class="hljs-comment">//链式调用</span><br><span class="hljs-meta">@JsonInclude(JsonInclude.Include.NON_NULL)</span><br><span class="hljs-meta">@TableName(value = &quot;sys_menu&quot;)</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Menu</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">Serializable</span> &#123;<br>    <span class="hljs-meta">@TableId</span><br>    <span class="hljs-keyword">private</span> Long id;<br><br>    <span class="hljs-keyword">private</span> String menuName;<br>    <span class="hljs-comment">//组件路径</span><br>    <span class="hljs-keyword">private</span> String path;<br>    <span class="hljs-comment">//组件名称</span><br>    <span class="hljs-keyword">private</span> String component;<br>    <span class="hljs-comment">//菜单状态</span><br>    <span class="hljs-keyword">private</span> String visible;<br>    <span class="hljs-keyword">private</span> String status;<br>    <span class="hljs-keyword">private</span> String perms;<br>    <span class="hljs-keyword">private</span> String icon;<br>    <span class="hljs-comment">//创建者</span><br>    <span class="hljs-keyword">private</span> Long  createBy;<br>    <span class="hljs-keyword">private</span> Date createTime;<br>    <span class="hljs-keyword">private</span> Long updateBy;<br>    <span class="hljs-keyword">private</span> Date updateTime;<br>    <span class="hljs-comment">//是否删除</span><br>    <span class="hljs-keyword">private</span> Integer delFlag;<br>    <span class="hljs-keyword">private</span> String remark;<br>&#125;<br></code></pre></td></tr></table></figure>

<h6 id="4-2-3-3代码实现"><a href="#4-2-3-3代码实现" class="headerlink" title="4.2.3.3代码实现"></a>4.2.3.3代码实现</h6><p>我们只需要根据用户id去查询其所对应的权限信息即可。</p>
<p>所以我们可以先定义一个mapper，其中提供一个方法可以根据userid查询权限信息。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Mapper</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title class_">MenuMapper</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">BaseMapper</span>&lt;Menu&gt; &#123;<br><span class="hljs-comment">// 根据用户id 查询perms 对应的role 和menu 都必须是正常状态的alter</span><br>    List&lt;String&gt; <span class="hljs-title function_">selectPermsByUserId</span><span class="hljs-params">(Long userId)</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>然后重新修改UserDetailsServiceImpl的代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.example.mybatisplusdemo.service.impl;<br><br><span class="hljs-keyword">import</span> com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;<br><span class="hljs-keyword">import</span> com.example.mybatisplusdemo.entity.LoginUser;<br><span class="hljs-keyword">import</span> com.example.mybatisplusdemo.entity.User;<br><br><span class="hljs-keyword">import</span> com.example.mybatisplusdemo.mapper.MenuMapper;<br><span class="hljs-keyword">import</span> com.example.mybatisplusdemo.mapper.UserMapper;<br><br><span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;<br><span class="hljs-keyword">import</span> org.springframework.security.core.userdetails.UserDetails;<br><span class="hljs-keyword">import</span> org.springframework.security.core.userdetails.UserDetailsService;<br><span class="hljs-keyword">import</span> org.springframework.security.core.userdetails.UsernameNotFoundException;<br><span class="hljs-keyword">import</span> org.springframework.stereotype.Service;<br><br><span class="hljs-keyword">import</span> java.util.ArrayList;<br><span class="hljs-keyword">import</span> java.util.Arrays;<br><span class="hljs-keyword">import</span> java.util.List;<br><span class="hljs-keyword">import</span> java.util.Objects;<br><br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> chenzj9</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Description</span> 重写security过滤器链中的UserDetailsService实现从数据库中查询用户信息</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@date</span> 2022年01月13日 16:39</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Service</span> <span class="hljs-comment">//注意一定要注入道spring容器中</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">UserDetailsServiceImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">UserDetailsService</span> &#123;<br>    <span class="hljs-meta">@Autowired</span><br>    <span class="hljs-keyword">private</span> UserMapper userMapper;<br><br>    <span class="hljs-meta">@Autowired</span><br>    <span class="hljs-keyword">private</span> MenuMapper menuMapper;<br>    <br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> UserDetails <span class="hljs-title function_">loadUserByUsername</span><span class="hljs-params">(String username)</span> <span class="hljs-keyword">throws</span> UsernameNotFoundException &#123;<br>    <span class="hljs-comment">//从数据库查询用户信息 这里我根据openID查询</span><br>        LambdaQueryWrapper&lt;User&gt; queryWrapper = <span class="hljs-keyword">new</span> <span class="hljs-title class_">LambdaQueryWrapper</span>&lt;&gt;();<br>        queryWrapper.eq(User::getUserName,username);<br>        <span class="hljs-type">User</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> userMapper.selectOne(queryWrapper);<br><span class="hljs-comment">//        如果查询到的用户信息为空，就抛出异常</span><br>        <span class="hljs-keyword">if</span>(Objects.isNull(user))&#123;<br>            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">&quot;用户openID错误或者是用户不存在&quot;</span>);<br>        &#125;<br>        <span class="hljs-comment">//TODO 查询用户的权限信息</span><br><span class="hljs-comment">//        List&lt;String&gt; permissions = new ArrayList&lt;&gt;(Arrays.asList(&quot;test&quot;));</span><br>        List&lt;String&gt; permissions = menuMapper.selectPermsByUserId(user.getId());<br><span class="hljs-comment">//        把数据封装成UserDetails</span><br><br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">LoginUser</span>(user,permissions);<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<p>然后修改接口中的权限信息</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RequestMapping(&quot;/hello&quot;)</span><br><span class="hljs-meta">@PreAuthorize(&quot;hasAuthority(&#x27;system:test:list&#x27;)&quot;)</span><span class="hljs-comment">//权限注解</span><br><span class="hljs-keyword">public</span> String <span class="hljs-title function_">Hello</span><span class="hljs-params">()</span>&#123;<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;ok&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>接着重新登陆、测试</p>
<h4 id="5-自定义失败处理"><a href="#5-自定义失败处理" class="headerlink" title="5.自定义失败处理"></a>5.自定义失败处理</h4><p>​	我们还希望再认证失败或者是授权失败的情况下也能和我们接口一样返回相同结构的json,这样就能让前端能对响应进行统一的处理。要实现这个功能我们需要知道SpringSecurity的异常处理机制。</p>
<p>​	在SpringSecurity中，如果我们在认证的或者授权的时候出现了异常会被ExceptionTranslationFilter捕获到。在ExceptionTranslationFilter中会去判断是认证失败还是授权失败出现的异常。</p>
<p>​	如果是认证过程中出现的异常会被封装成AuthenticationException然后调用AccessDeniedHandler对象的方法进行异常处理。</p>
<p>​	所以如果我们需要自定义异常处理，我们只需要自定义AuthenticationEntryPoint和AccessDeniedHandle然后配置给SpringSecurity即可。</p>
<p>1.自定义实现类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Component</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">AuthenticationEntryPointImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">AuthenticationEntryPoint</span> &#123;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">commence</span><span class="hljs-params">(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e)</span> <span class="hljs-keyword">throws</span> IOException, ServletException &#123;<br>        <span class="hljs-type">Result</span> <span class="hljs-variable">result</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Result</span>(HttpStatus.UNAUTHORIZED.value(), <span class="hljs-string">&quot;用户认证失败，请重新登录！&quot;</span>,<span class="hljs-literal">null</span>);<br>        <span class="hljs-type">String</span> <span class="hljs-variable">json</span> <span class="hljs-operator">=</span> JSON.toJSONString(result);<br>        <span class="hljs-comment">//处理异常</span><br>        WebUtils.renderString(httpServletResponse,json);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.example.mybatisplusdemo.handler;<br><br><span class="hljs-keyword">import</span> com.alibaba.fastjson.JSON;<br><span class="hljs-keyword">import</span> com.example.mybatisplusdemo.utils.Result;<br><span class="hljs-keyword">import</span> com.example.mybatisplusdemo.utils.WebUtils;<br><span class="hljs-keyword">import</span> org.springframework.http.HttpStatus;<br><span class="hljs-keyword">import</span> org.springframework.security.access.AccessDeniedException;<br><span class="hljs-keyword">import</span> org.springframework.security.web.access.AccessDeniedHandler;<br><span class="hljs-keyword">import</span> org.springframework.stereotype.Component;<br><br><span class="hljs-keyword">import</span> javax.servlet.ServletException;<br><span class="hljs-keyword">import</span> javax.servlet.http.HttpServletRequest;<br><span class="hljs-keyword">import</span> javax.servlet.http.HttpServletResponse;<br><span class="hljs-keyword">import</span> java.io.IOException;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> chenzj9</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Description</span></span><br><span class="hljs-comment"> * <span class="hljs-doctag">@date</span> 2022年01月21日 16:12</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Component</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">AccessDeniedHandlerImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">AccessDeniedHandler</span> &#123;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">handle</span><span class="hljs-params">(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e)</span> <span class="hljs-keyword">throws</span> IOException, ServletException &#123;<br>        <span class="hljs-type">Result</span> <span class="hljs-variable">result</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Result</span>(HttpStatus.FORBIDDEN.value(), <span class="hljs-string">&quot;用户授权失败或者您的权限不足，请重新登录！&quot;</span>,<span class="hljs-literal">null</span>);<br>        <span class="hljs-type">String</span> <span class="hljs-variable">json</span> <span class="hljs-operator">=</span> JSON.toJSONString(result);<br>        <span class="hljs-comment">//处理异常</span><br>        WebUtils.renderString(httpServletResponse,json);<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<p>定义转json的工具类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.example.mybatisplusdemo.utils;<br><br><span class="hljs-keyword">import</span> javax.servlet.http.HttpServletResponse;<br><span class="hljs-keyword">import</span> java.io.IOException;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> chenzj9</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Description</span> 将字符串渲染到客户端</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@date</span> 2022年01月21日 15:59</span><br><span class="hljs-comment"> */</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">WebUtils</span> &#123;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@Description</span>: 将字符串渲染到客户端</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@author</span>: chenzj9</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@date</span>: 2022/1/21 16:02</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> response 渲染对象</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> string 待渲染的字符串</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span> java.lang.String</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title function_">renderString</span><span class="hljs-params">(HttpServletResponse response,String string)</span>&#123;<br>        <span class="hljs-keyword">try</span>&#123;<br>            response.setStatus(<span class="hljs-number">200</span>);<br>            response.setContentType(<span class="hljs-string">&quot;application/json&quot;</span>);<br>            response.setCharacterEncoding(<span class="hljs-string">&quot;utf-8&quot;</span>);<br>            response.getWriter().print(string);<br>        &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>



<p>2.配置给SpringSecurity</p>
<p>​	我们可以使用HttpSecurity对象的方法去配置。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.example.mybatisplusdemo.config;<br><br><span class="hljs-keyword">import</span> com.example.mybatisplusdemo.filter.JwtAuthenticationTokenFilter;<br><span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;<br><span class="hljs-keyword">import</span> org.springframework.context.annotation.Bean;<br><span class="hljs-keyword">import</span> org.springframework.context.annotation.Configuration;<br><span class="hljs-keyword">import</span> org.springframework.security.authentication.AuthenticationManager;<br><span class="hljs-keyword">import</span> org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;<br><span class="hljs-keyword">import</span> org.springframework.security.config.annotation.web.builders.HttpSecurity;<br><span class="hljs-keyword">import</span> org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;<br><span class="hljs-keyword">import</span> org.springframework.security.config.http.SessionCreationPolicy;<br><span class="hljs-keyword">import</span> org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;<br><span class="hljs-keyword">import</span> org.springframework.security.crypto.password.PasswordEncoder;<br><span class="hljs-keyword">import</span> org.springframework.security.web.AuthenticationEntryPoint;<br><span class="hljs-keyword">import</span> org.springframework.security.web.access.AccessDeniedHandler;<br><span class="hljs-keyword">import</span> org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> chenzj9</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Description</span> security配置类</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@date</span> 2022年01月13日 17:44</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Configuration</span><br><span class="hljs-meta">@EnableGlobalMethodSecurity(prePostEnabled = true)</span> <span class="hljs-comment">//开启是用prePostEnabled的注解</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">SpringSecurityConfig</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">WebSecurityConfigurerAdapter</span> &#123;<br>    <span class="hljs-comment">//    BCryptPasswordEncoder创建默认的密码加密方式并注入容器</span><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> PasswordEncoder <span class="hljs-title function_">passwordEncoder</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">BCryptPasswordEncoder</span>();<br>    &#125;<br><br>    <span class="hljs-meta">@Autowired</span><br>    <span class="hljs-keyword">private</span> JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;<br><span class="hljs-comment">//    重写方法实现放行请求</span><br><br>    <span class="hljs-meta">@Autowired</span><br>    <span class="hljs-keyword">private</span> AuthenticationEntryPoint authenticationEntryPoint;<br>    <span class="hljs-meta">@Autowired</span><br>    <span class="hljs-keyword">private</span> AccessDeniedHandler accessDeniedHandler;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">configure</span><span class="hljs-params">(HttpSecurity http)</span> <span class="hljs-keyword">throws</span> Exception &#123;<br>        http<br>                .csrf().disable() <span class="hljs-comment">//关闭csrf</span><br><span class="hljs-comment">//                关闭session会话机制</span><br>                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)<br>                .and()<br>                .authorizeRequests()<br>                <span class="hljs-comment">//对于登录接口 允许匿名访问</span><br>                .antMatchers(<span class="hljs-string">&quot;/user/login&quot;</span>).anonymous()<br>                <span class="hljs-comment">//除了上面的都要进行鉴权认证</span><br>                .anyRequest().authenticated();<br><span class="hljs-comment">//        super.configure(http);</span><br>        http<br><span class="hljs-comment">//                在UsernamePasswordAuthenticationFilter之前添加过滤器</span><br>                .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);<br>        <span class="hljs-comment">//配置异常处理器</span><br>        http.exceptionHandling()<br>                <span class="hljs-comment">//认证失败处理器</span><br>                .authenticationEntryPoint(authenticationEntryPoint)<br>                .and()<br>                <span class="hljs-comment">//授权失败处理器</span><br>                .exceptionHandling().accessDeniedHandler(accessDeniedHandler);<br>    &#125;<br><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> AuthenticationManager <span class="hljs-title function_">authenticationManagerBean</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> Exception &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">super</span>.authenticationManagerBean();<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<h4 id="6-跨域"><a href="#6-跨域" class="headerlink" title="6.跨域"></a>6.跨域</h4><p>​	浏览器处于安全的考虑，使用XMLHttpRequest对象发起Http请求时必须遵循同源策略，否则就是跨域的Http请求，默认情况下是被禁止的。同源策略要求源相同才能进行正常通信，即协议、域名、端口号都完全一致。</p>
<p>​	前后端分离项目，前端项目和后端项目一般都不是同源的。所以肯定会存在跨域请求的问题。</p>
<p>​	所以我们就要处理一下，让前端能进行跨域请求。</p>
<p>1.先对SpringBoot配置，允许跨域请求</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.example.mybatisplusdemo.configuration;<br><br><span class="hljs-keyword">import</span> org.springframework.context.annotation.Configuration;<br><span class="hljs-keyword">import</span> org.springframework.web.servlet.config.annotation.CorsRegistry;<br><span class="hljs-keyword">import</span> org.springframework.web.servlet.config.annotation.WebMvcConfigurer;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> chenzj9</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Description</span> 解决跨域问题</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@date</span> 2021年11月30日 17:06</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Configuration</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">CrosConfiguration</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">WebMvcConfigurer</span> &#123;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">addCorsMappings</span><span class="hljs-params">(CorsRegistry registry)</span> &#123;<br>        <span class="hljs-comment">//设置允许跨域的路径</span><br>        registry.addMapping(<span class="hljs-string">&quot;/**&quot;</span>)<br>                <span class="hljs-comment">//设置允许跨域请求的域名</span><br>                .allowedOriginPatterns(<span class="hljs-string">&quot;*&quot;</span>)<br>                <span class="hljs-comment">//设置允许请求的方式</span><br>                .allowedMethods(<span class="hljs-string">&quot;GET&quot;</span>, <span class="hljs-string">&quot;HEAD&quot;</span>, <span class="hljs-string">&quot;POST&quot;</span>, <span class="hljs-string">&quot;PUT&quot;</span>, <span class="hljs-string">&quot;DELETE&quot;</span>, <span class="hljs-string">&quot;OPTIONS&quot;</span>)<br>                <span class="hljs-comment">//  是否允许cookie</span><br>                .allowCredentials(<span class="hljs-literal">true</span>)<br>                <span class="hljs-comment">//跨域允许时间</span><br>                .maxAge(<span class="hljs-number">3600</span>)<br>                <span class="hljs-comment">//跨域允许的header属性</span><br>                .allowedHeaders(<span class="hljs-string">&quot;*&quot;</span>);<br>        WebMvcConfigurer.<span class="hljs-built_in">super</span>.addCorsMappings(registry);<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<p>2.配置SpringSecurity的配置类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><code class="hljs java">    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">configure</span><span class="hljs-params">(HttpSecurity http)</span> <span class="hljs-keyword">throws</span> Exception &#123;<br>        http<br>                .csrf().disable() <span class="hljs-comment">//关闭csrf</span><br><span class="hljs-comment">//                关闭session会话机制</span><br>                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)<br>                .and()<br>                .authorizeRequests()<br>                <span class="hljs-comment">//对于登录接口 允许匿名访问</span><br>                .antMatchers(<span class="hljs-string">&quot;/user/login&quot;</span>).anonymous()<br>                <span class="hljs-comment">//除了上面的都要进行鉴权认证</span><br>                .anyRequest().authenticated();<br><span class="hljs-comment">//        super.configure(http);</span><br>        http<br><span class="hljs-comment">//                在UsernamePasswordAuthenticationFilter之前添加过滤器</span><br>                .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);<br>        <span class="hljs-comment">//配置异常处理器</span><br>        http.exceptionHandling()<br>                <span class="hljs-comment">//认证失败处理器</span><br>                .authenticationEntryPoint(authenticationEntryPoint)<br>                .and()<br>                <span class="hljs-comment">//授权失败处理器</span><br>                .exceptionHandling().accessDeniedHandler(accessDeniedHandler);<br>       <span class="hljs-comment">//允许SpringSecurity跨域</span><br>        http.cors();<br>    &#125;<br></code></pre></td></tr></table></figure>

<p>在浏览器中测试</p>
<h4 id="7-遗留小问题"><a href="#7-遗留小问题" class="headerlink" title="7.遗留小问题"></a>7.遗留小问题</h4><h5 id="其他权限校验方法"><a href="#其他权限校验方法" class="headerlink" title="其他权限校验方法"></a>其他权限校验方法</h5><p>​	我们前面都是使用@PreAuthorize注册，然后再在其中使用的hasAuthority方法进行校验。SpringSecurity还为我们提供了其他的方法，例如：hasAnyAuthority，hasRole，hasAnyRole，等。</p>
<p>​	这里我们先不急着去介绍这些方法，我们先去理解hasAuthority的原理，然后再去学习其他的方法你就更容易理解，而不是死记硬背区别。并且我们也可以选择定义校验方法，实现我们自己的校验逻辑。</p>
<p>​	hasAuthority方法实际上是执行到了SecurityExpressionRoot的hasAuthority，大家只要根据断点调试即可知道它内部校验原理。</p>
<p>​	它内部其实是调用Authentication的getAuthorities方法获取用户的权限列表。然后判断我们存入的方法参数数据在权限列表中。</p>
<p>​	hasAnyAuthority方法可以传入多个权限，只有用户有其中的任意一个权限就可以访问对应资源。</p>
<p>​	hasRole要求有对应的角色才能访问，但是它内部会把我们传入的参数拼接上<strong>ROLE _</strong>   后在去比较。所以中情况下要用用户对应的权限也要有<strong>ROLE_</strong>  这个前缀才行。</p>
<p>​	hasAnyRole要求任意的角色才能访问，但是它内部会把我们传入的参数拼接上<strong>ROLE _</strong>   后在去比较。所以中情况下要用用户对应的权限也要有<strong>ROLE_</strong>  这个前缀才行。</p>
<h5 id="自定义权限校验方法"><a href="#自定义权限校验方法" class="headerlink" title="自定义权限校验方法"></a>自定义权限校验方法</h5><p>​	我们也可以定义自己的权限检验方法。在@PreAuthorize注解中使用我们的方法。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.example.mybatisplusdemo.expression;<br><br><span class="hljs-keyword">import</span> com.example.mybatisplusdemo.entity.LoginUser;<br><span class="hljs-keyword">import</span> org.springframework.security.core.Authentication;<br><span class="hljs-keyword">import</span> org.springframework.security.core.context.SecurityContextHolder;<br><span class="hljs-keyword">import</span> org.springframework.stereotype.Component;<br><br><span class="hljs-keyword">import</span> java.util.List;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> chenzj9</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Description</span> 自定义权限校验方法</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@date</span> 2022年01月21日 22:10</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Component(&quot;ex&quot;)</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">SGExpressionRoot</span> &#123;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">hasAuthority</span><span class="hljs-params">(String authority)</span>&#123;<br>        <span class="hljs-comment">//获取当前用户的权限</span><br>        <span class="hljs-type">Authentication</span> <span class="hljs-variable">authentication</span> <span class="hljs-operator">=</span> SecurityContextHolder.getContext().getAuthentication();<br>        <span class="hljs-type">LoginUser</span> <span class="hljs-variable">loginUser</span> <span class="hljs-operator">=</span> (LoginUser) authentication.getPrincipal();<br>        List&lt;String&gt; permission = loginUser.getPermission();<br>        <span class="hljs-comment">//判断用户权限集合中是否存在authority</span><br>        <span class="hljs-keyword">return</span> permission.contains(authority);<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<p>新增接口方法测试(注意使用@ex相当于获取bean容器中的名字为ex的对象，然后就能调用bean中的自定义方法)</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RequestMapping(&quot;/test&quot;)</span><br><span class="hljs-meta">@PreAuthorize(&quot;@ex.hasAuthority(&#x27;system:test:list&#x27;)&quot;)</span> <span class="hljs-comment">//自定义权限规则校验</span><br><span class="hljs-keyword">public</span> String <span class="hljs-title function_">Test</span><span class="hljs-params">()</span> &#123;<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;ok&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>



<h5 id="基于配置的权限控制"><a href="#基于配置的权限控制" class="headerlink" title="基于配置的权限控制"></a>基于配置的权限控制</h5><p>​	我们也可以在配置类中使用配置的方法对资源进行权限控制</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> chenzj9</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Description</span> security配置类</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@date</span> 2022年01月13日 17:44</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Configuration</span><br><span class="hljs-meta">@EnableGlobalMethodSecurity(prePostEnabled = true)</span> <span class="hljs-comment">//开启是用prePostEnabled的注解</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">SpringSecurityConfig</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">WebSecurityConfigurerAdapter</span> &#123;<br>    <span class="hljs-comment">//    BCryptPasswordEncoder创建默认的密码加密方式并注入容器</span><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> PasswordEncoder <span class="hljs-title function_">passwordEncoder</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">BCryptPasswordEncoder</span>();<br>    &#125;<br><br>    <span class="hljs-meta">@Autowired</span><br>    <span class="hljs-keyword">private</span> JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;<br><span class="hljs-comment">//    重写方法实现放行请求</span><br><br>    <span class="hljs-meta">@Autowired</span><br>    <span class="hljs-keyword">private</span> AuthenticationEntryPoint authenticationEntryPoint;<br>    <span class="hljs-meta">@Autowired</span><br>    <span class="hljs-keyword">private</span> AccessDeniedHandler accessDeniedHandler;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">configure</span><span class="hljs-params">(HttpSecurity http)</span> <span class="hljs-keyword">throws</span> Exception &#123;<br>        http<br>                .csrf().disable() <span class="hljs-comment">//关闭csrf</span><br><span class="hljs-comment">//                关闭session会话机制</span><br>                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)<br>                .and()<br>                .authorizeRequests()<br>                <span class="hljs-comment">//对于登录接口 允许匿名访问</span><br>                .antMatchers(<span class="hljs-string">&quot;/user/login&quot;</span>).anonymous()<br>                .antMatchers(<span class="hljs-string">&quot;/config/testAuthority&quot;</span>).hasAuthority(<span class="hljs-string">&quot;system:test:list&quot;</span>) <span class="hljs-comment">//也可以在这里配置接口所需权限字符 当然也可以使用其他的方法比如hasROLE()、hasAnyAuthority()等</span><br>                <span class="hljs-comment">//除了上面的都要进行鉴权认证</span><br>                .anyRequest().authenticated();<br><span class="hljs-comment">//        super.configure(http);</span><br>        http<br><span class="hljs-comment">//                在UsernamePasswordAuthenticationFilter之前添加过滤器</span><br>                .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);<br>        <span class="hljs-comment">//配置异常处理器</span><br>        http.exceptionHandling()<br>                <span class="hljs-comment">//认证失败处理器</span><br>                .authenticationEntryPoint(authenticationEntryPoint)<br>                .and()<br>                <span class="hljs-comment">//授权失败处理器</span><br>                .exceptionHandling().accessDeniedHandler(accessDeniedHandler);<br>        <span class="hljs-comment">//允许SpringSecurity跨域</span><br>        http.cors();<br>    &#125;<br><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> AuthenticationManager <span class="hljs-title function_">authenticationManagerBean</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> Exception &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">super</span>.authenticationManagerBean();<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<p>然后新增接口测试</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@GetMapping(&quot;/config/testAuthority&quot;)</span><br><span class="hljs-keyword">public</span> Result <span class="hljs-title function_">testAuthority</span><span class="hljs-params">()</span>&#123;<br>    <span class="hljs-keyword">return</span> Result.success(<span class="hljs-string">&quot;访问成功!&quot;</span>);<br>&#125;<br></code></pre></td></tr></table></figure>

<h5 id="CSRF"><a href="#CSRF" class="headerlink" title="CSRF"></a>CSRF</h5><p>​	CRSF是只跨站请求伪造（Cross-site request forgery），是web常见的攻击之一。</p>
<p>​	SpringSecurity去防止CRSF攻击的方式就是通过crsf_token。后端会生成一个crsf_token，前端发起请求的时候需要携带这个crsf_token后端会有过滤器进行检验，如果没有携带或者是伪造的就不允许访问。</p>
<p>​	我们可以发现CRSF攻击依靠的是cookie中所携带的认证信息。但是在前后端分离的项目中，我们的认证信息其实是token，而token并不是存储在cookie中，并且需要前端代码去把token设置的请求中才可以，所以CRSF攻击就不用担心了。</p>
<h5 id="认证成功处理器"><a href="#认证成功处理器" class="headerlink" title="认证成功处理器"></a>认证成功处理器</h5><p>​	实际上在UsernamePasswordAuthenFilter进行登录认证的时候，如果登录认证成功了是会调用AuthenticationSuccessHandler的方法进行认证成功后的处理的。AuthenticationSuccessHandler就是登录成功处理器。</p>
<p>​	我们也可以自己去自定义成功处理器进行成功后的相应处理。</p>
<p>​	注意：这时候就不能使用之前的项目进行测试了，因为现在的项目在config阶段时已经没有了UsernamePasswordAuthenFilter了，所以要重新创建项目测试。</p>
<h5 id="认证成功处理器-1"><a href="#认证成功处理器-1" class="headerlink" title="认证成功处理器"></a>认证成功处理器</h5><h5 id="其他认证方案"><a href="#其他认证方案" class="headerlink" title="其他认证方案"></a>其他认证方案</h5><p>实际上在UsernamePasswordAuthenticationFilter进行认证的时候，如果认证失败了是会调用AuthenticationFailureHandler的方法进行认证失败后的处理的。AuthenticationFailureHandler就是认证失败处理器。</p>
<p>​	我们也可以自定义认证失败处理器进行失败后的相应处理。注意这时候也不能用原本的项目实现改功能</p>

                
              </div>
            
            <hr/>
            <div>
              <div class="post-metas my-3">
  
  
</div>


              
  

  <div class="license-box my-3">
    <div class="license-title">
      <div>SpringBoot整合Security</div>
      <div>http://czrgitee.gitee.io/2022/08/25/SpringBoot整合Security/</div>
    </div>
    <div class="license-meta">
      
        <div class="license-meta-item">
          <div>作者</div>
          <div>czr</div>
        </div>
      
      
        <div class="license-meta-item license-meta-date">
          <div>发布于</div>
          <div>2022年8月25日</div>
        </div>
      
      
      
        <div class="license-meta-item">
          <div>许可协议</div>
          <div>
            
              
              
                <a target="_blank" href="https://creativecommons.org/licenses/by/4.0/">
                  <span class="hint--top hint--rounded" aria-label="BY - 署名">
                    <i class="iconfont icon-by"></i>
                  </span>
                </a>
              
            
          </div>
        </div>
      
    </div>
    <div class="license-icon iconfont"></div>
  </div>



              
                <div class="post-prevnext my-3">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2022/10/13/%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5/" title="螺旋矩阵">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">螺旋矩阵</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2022/08/12/Typora-PicGo%E8%87%AA%E5%8A%A8%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87%E5%88%B0Gitee/" title="Typora+PicGo自动上传图片到Gitee">
                        <span class="hidden-mobile">Typora+PicGo自动上传图片到Gitee</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>

    <div class="side-col d-none d-lg-block col-lg-2">
      
  <aside class="sidebar" style="margin-left: -1rem">
    <div id="toc">
  <p class="toc-header">
    <i class="iconfont icon-list"></i>
    <span>目录</span>
  </p>
  <div class="toc-body" id="toc-body"></div>
</div>



  </aside>


    </div>
  </div>
</div>





  



  



  



  



  







    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v" for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>

    

    
  </main>

  <footer>
    <div class="footer-inner">
  
    <div class="footer-content">
       <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Andersen</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>blog</span></a> 
    </div>
  
  
  
  
</div>

  </footer>

  <!-- Scripts -->
  
  <script  src="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js" ></script>
<script  src="https://lib.baomitu.com/twitter-bootstrap/4.6.1/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>


  <script  src="https://lib.baomitu.com/typed.js/2.0.12/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var subtitle = document.getElementById('subtitle');
      if (!subtitle || !typing) {
        return;
      }
      var text = subtitle.getAttribute('data-typed-text');
      
        typing(text);
      
    })(window, document);
  </script>




  
    <script  src="/js/img-lazyload.js" ></script>
  




  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/tocbot/4.18.2/tocbot.min.js', function() {
    var toc = jQuery('#toc');
    if (toc.length === 0 || !window.tocbot) { return; }
    var boardCtn = jQuery('#board-ctn');
    var boardTop = boardCtn.offset().top;

    window.tocbot.init(Object.assign({
      tocSelector     : '#toc-body',
      contentSelector : '.markdown-body',
      linkClass       : 'tocbot-link',
      activeLinkClass : 'tocbot-active-link',
      listClass       : 'tocbot-list',
      isCollapsedClass: 'tocbot-is-collapsed',
      collapsibleClass: 'tocbot-is-collapsible',
      scrollSmooth    : true,
      includeTitleTags: true,
      headingsOffset  : -boardTop,
    }, CONFIG.toc));
    if (toc.find('.toc-list-item').length > 0) {
      toc.css('visibility', 'visible');
    }

    Fluid.events.registerRefreshCallback(function() {
      if ('tocbot' in window) {
        tocbot.refresh();
        var toc = jQuery('#toc');
        if (toc.length === 0 || !tocbot) {
          return;
        }
        if (toc.find('.toc-list-item').length > 0) {
          toc.css('visibility', 'visible');
        }
      }
    });
  });
</script>


  <script src=https://lib.baomitu.com/clipboard.js/2.0.10/clipboard.min.js></script>

  <script>Fluid.plugins.codeWidget();</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/anchor-js/4.3.1/anchor.min.js', function() {
    window.anchors.options = {
      placement: CONFIG.anchorjs.placement,
      visible  : CONFIG.anchorjs.visible
    };
    if (CONFIG.anchorjs.icon) {
      window.anchors.options.icon = CONFIG.anchorjs.icon;
    }
    var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
    var res = [];
    for (var item of el) {
      res.push('.markdown-body > ' + item.trim());
    }
    if (CONFIG.anchorjs.placement === 'left') {
      window.anchors.options.class = 'anchorjs-link-left';
    }
    window.anchors.add(res.join(', '));

    Fluid.events.registerRefreshCallback(function() {
      if ('anchors' in window) {
        anchors.removeAll();
        var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
        var res = [];
        for (var item of el) {
          res.push('.markdown-body > ' + item.trim());
        }
        if (CONFIG.anchorjs.placement === 'left') {
          anchors.options.class = 'anchorjs-link-left';
        }
        anchors.add(res.join(', '));
      }
    });
  });
</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.js', function() {
    Fluid.plugins.fancyBox();
  });
</script>


  <script>Fluid.plugins.imageCaption();</script>

  <script  src="/js/local-search.js" ></script>





<!-- 主题的启动项，将它保持在最底部 -->
<!-- the boot of the theme, keep it at the bottom -->
<script  src="/js/boot.js" ></script>


  

  <noscript>
    <div class="noscript-warning">博客在允许 JavaScript 运行的环境下浏览效果更佳</div>
  </noscript>
</body>
</html>
